package com.wavecoler.servlets;
 //tomado de http://code.google.com/p/kenji/source/browse/RobotMultiplexer/trunk/src/jp/rainbowdevil/robotmultiplexer/AbstractRobotMultiplexer.java


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import com.google.wave.api.AbstractRobot;
import com.google.wave.api.impl.EventMessageBundle;
/**
 * RobotMultiplexer<br><br>
 * 
 * AbstractRobotMultiplexer web.xml <br>
 * AbstractRobotMultiplexer initRobots addRobot <br><br>
 * 
 * sample.APP_ID@appspot.com ID  SampleRobot<br>
 * addRobot( "sample" , new SampleRobot() );  <br><br>
 * 
 * @author kitamura
 *
 */
abstract public class AbstractRobotMultiplexer extends AbstractRobot {
	
/** Robot instance map */
	private Map<String,AbstractRobot> robotMap = new HashMap<String, AbstractRobot>();
/** Serializer to serialize events and operations in the event-based mode. */
//	private static final Gson SERIALIZER = new GsonFactory().create();

/** logger */
	private static Logger logger = Logger.getLogger(AbstractRobotMultiplexer.class.getName());

/**
* constructor
*/
public AbstractRobotMultiplexer() {
	initRobots();
}

@Override
protected String getRobotName() {
 throw new IllegalStateException("DO NOT CALL THIS METHOD!");
 }

@Override
protected String getRobotAvatarUrl() {
 throw new IllegalStateException("DO NOT CALL THIS METHOD!");
}

@Override
protected String getRobotProfilePageUrl() {
	throw new IllegalStateException("DO NOT CALL THIS METHOD!");
}

/**
 * Add robot instance
 * @param prefix
 * @param robot
  */

public void addRobot(String prefix, AbstractRobot robot) {
	prefix = prefix.toLowerCase();
	logger.fine("RobotMultiplexer : add robot  prefix=(" + prefix + ") robot class=" + robot.getClass().getName()); 
	robotMap.put(prefix, robot);
	}

/** init your robots. */
abstract public void initRobots();
/**
 * extract robot prefix
 * @param robotAddress
 * @return
 */
private String getPrefix(String robotAddress) {
	String delimiter = "@"; // doPost
	int atIndex = robotAddress.indexOf(delimiter);
	if( atIndex == -1 ){
		delimiter = ".appspot.com"; // doGet
		atIndex = robotAddress.indexOf(delimiter);
}

	if (atIndex != -1) {
		String username = robotAddress.substring(0, atIndex);
		int lastDotIndex = username.lastIndexOf(".");
		if (lastDotIndex != -1) {
			String prefix = username.substring(0, lastDotIndex);
			return prefix;
		}
	}
	return null;
}
/**
 * doPost...
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
	String prefix = getPrefix(req.getServerName());
	AbstractRobot robot = robotMap.get(prefix);
	if( robot == null){
    	return ;
    }
//---------------------------------------------------------
// call doPost
try {
	Method method = AbstractRobot.class.getDeclaredMethod("doPost", new Class[] {
			HttpServletRequest.class,
			HttpServletResponse.class });
	method.setAccessible(true);
	method.invoke(robot, req, resp);
} catch (Exception e) {
	throw new RuntimeException("fail invoke doPost method.",e);
  }
//---------------------------------------------------------
}


/**
  * doGet
  */
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {

	String prefix = getPrefix(req.getServerName());
	AbstractRobot robot = robotMap.get(prefix);
	if( robot == null ){
		return ;
	}

	//---------------------------------------------------------
	// call doGet
	try {
	Method method = AbstractRobot.class.getDeclaredMethod("doGet", new Class[] {
			HttpServletRequest.class,
			HttpServletResponse.class });
	method.setAccessible(true);
	method.invoke(robot, req, resp);
	} catch (Exception e) {
		throw new RuntimeException("fail invoke doGet method.",e);
	}
	//---------------------------------------------------------
}

/**
 * HttpServletRequest Robot
 *  
 *  @param req
 *  @return
 */
protected AbstractRobot getRobot( HttpServletRequest req ){
	String prefix = getPrefix(req.getServerName()).toLowerCase();
	AbstractRobot robot = robotMap.get(prefix);
	if( robot == null ){
		String message = "Not found robot. prefix="+prefix +" ServerName="+req.getServerName();
		logger.severe(message);
	}
	return robot;
}

/**
 * EventMessageBuldle Robot
 *  
 *  null
 *  @param event
 *  @return
*/

protected AbstractRobot getRobot( EventMessageBundle event ){
	String prefix = getPrefix(event.getRobotAddress()).toLowerCase();
	AbstractRobot robot = robotMap.get(prefix);
	if( robot == null ){
		String message = "Not found robot. prefix="+prefix +" RobotAddress="+event.getRobotAddress();
		logger.severe(message);
	}
	return robot;
}
}